package handlers

import (
	"backend/internal/database"
	"backend/models"
	"backend/pkg/log"
	"backend/pkg/utils"
	"fmt"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
)

func RequestPasswordReset(c *gin.Context) {
	startTime := time.Now()
	var req struct {
		Email string `json:"email" binding:"required,email"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		log.Error("请求参数绑定失败: %v", err)
		c.JSON(http.StatusBadRequest, gin.H{"error": "邮箱格式不正确"})
		log.RequestLog(c, startTime, "请求参数绑定失败")
		return
	}

	// 检查用户是否存在
	var user models.User
	if result := database.DB.Where("email = ?", req.Email).First(&user); result.Error != nil {
		log.Warning("用户不存在: %s", req.Email)
		c.JSON(http.StatusOK, gin.H{"message": "如果邮箱存在，重置链接将发送到该邮箱"})
		log.RequestLog(c, startTime, "用户不存在")
		return
	}

	// 生成验证码
	code, expiresAt := generateVerificationCode()
	emailVerificationCodes[req.Email] = struct {
		code      string
		expiresAt time.Time
	}{code, expiresAt}

	// 计算过期时间（分钟）
	expiryMinutes := int(getVerificationCodeExpiry().Minutes())
	// 发送重置密码邮件
	emailBody := fmt.Sprintf("您的密码重置验证码是: %s\n验证码有效期为%d分钟。", code, expiryMinutes)
	if err := utils.SendEmail(req.Email, "密码重置", emailBody); err != nil {
		log.Error("重置密码邮件发送失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "邮件发送失败"})
		log.RequestLog(c, startTime, "邮件发送失败")
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "重置密码的验证码已发送到您的邮箱",
	})
	log.RequestLog(c, startTime, "重置密码邮件发送成功")
}

func ConfirmPasswordReset(c *gin.Context) {
	startTime := time.Now()
	var req struct {
		Email       string `json:"email" binding:"required,email"`
		Code        string `json:"code" binding:"required"`
		NewPassword string `json:"newPassword" binding:"required,min=6"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		log.Error("请求参数绑定失败: %v", err)
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		log.RequestLog(c, startTime, "请求参数绑定失败")
		return
	}

	// 验证验证码
	if !VerifyEmailCode(req.Email, req.Code) {
		log.Warning("验证码错误或已过期: %s", req.Email)
		c.JSON(http.StatusBadRequest, gin.H{"error": "验证码错误或已过期，请重新获取"})
		log.RequestLog(c, startTime, "验证码错误或已过期")
		return
	}

	// 更新密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
	if err != nil {
		log.Error("密码加密失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "密码重置失败"})
		log.RequestLog(c, startTime, "密码加密失败")
		return
	}

	result := database.DB.Model(&models.User{}).Where("email = ?", req.Email).Update("password", string(hashedPassword))
	if result.Error != nil {
		log.Error("密码更新失败: %v", result.Error)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "密码重置失败"})
		log.RequestLog(c, startTime, "密码更新失败")
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "密码重置成功"})
	log.RequestLog(c, startTime, "密码重置成功")
}
